﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.ComponentModel;

namespace Enter.DataCommon
{
	/// <summary>
	/// DataMap/DataReadonly的数据装载器
	/// </summary>
	public static class DataLoader
	{
		static DataLoader()
		{
			//_UniqueKey = UniqueKey.Default;
		}

		#region First

		/// <summary>
		/// 把DataTable第一行的值转换成 T 类型
		/// </summary>
		/// <typeparam name="T">从DataMap或DataReadonly继承的类型</typeparam>
		/// <param name="table">System.Data.DataTable</param>
		/// <returns></returns>
		public static T First<T>(DataTable table)
		{
			if (table == null || table.Rows.Count < 1)
				return default(T);// 没有数据，返回空。

			T t = Activator.CreateInstance<T>();
			Load<T>(t, table.Rows[0]);

			return t;
		}
		/// <summary>
		/// 把IDataReader第一行的值转换成 T 类型
		/// </summary>
		/// <typeparam name="T">从DataMap或DataReadonly继承的类型</typeparam>
		/// <param name="reader">System.Data.IDataReader</param>
		/// <returns></returns>
		public static T First<T>(IDataReader reader)
		{
			if (reader == null)
				return default(T);
			while (reader.Read())
			{
				T t = Activator.CreateInstance<T>();
				Load<T>(t, reader);
				// 将对象置为修改状态
				//SetDataMapToModified<T>(t);

				return t;
			}
            return default(T);// 没有数据，返回空。
		}

		#endregion

		#region ToList

		private static void Foreach<T>(IList<T> output, DataTable target, Action<T, object[]> loader) 
		{
			for (int i = 0; i < target.Rows.Count; i++)
			{
				T dataObj = Activator.CreateInstance<T>();
				loader(dataObj, target.Rows[i].ItemArray);
				output.Add(dataObj);
			}
		}
		private static void Foreach<T>(IList<T> output, IDataReader target, Action<T, object[]> loader)
		{
			object[] source = new object[target.FieldCount];
			while (target.Read())
			{
				T t = Activator.CreateInstance<T>();
				target.GetValues(source);
				loader(t, source);
				output.Add(t);
			}
		}

		/// <summary>
		/// 把DataTable转换成 T 类型的list集合
		/// </summary>
		/// <typeparam name="T">从DataMap或DataReadonly继承的类型</typeparam>
		/// <param name="table">System.Data.DataTable</param>
		/// <returns>类 T 集合。</returns>
		public static IList<T> ToList<T>(DataTable table)
		{
			if (table == null || table.Rows.Count < 1)
				return new List<T>(0);

			List<T> list = new List<T>(table.Rows.Count);

            foreach (DataRow dr in table.Rows)
            {
                T t = Activator.CreateInstance<T>();
                Load<T>(t, dr);
                list.Add(t);
            }
			// 
			return list;
		}
		/// <summary>
		/// 把DataTable转换成 T 类型的list集合
		/// </summary>
		/// <typeparam name="T">从DataMap或DataReadonly继承的类型</typeparam>
		/// <param name="reader">System.Data.IDataReader，注：reader在使用完后会被关闭。</param>
		/// <returns>类 T 集合。</returns>
		public static IList<T> ToList<T>(IDataReader reader)
		{
			if (reader == null)
				return new List<T>(0);

			int capacity = reader.RecordsAffected > 0 ? reader.RecordsAffected : 4;
			List<T> list = new List<T>(capacity);

			while (reader.Read())
			{
				T t = Activator.CreateInstance<T>();
				Load(t, reader);
				list.Add(t);
			}
			
			return list;
		}
		#endregion


		#region Load

		/// <summary>
		/// 加载数据
		/// </summary>
		/// <param name="dr">一行数据</param>
		public static void Load<T>(T output, DataRow dr)
		{
			if (dr == null)
				return;

			DataColumnCollection columns = dr.Table.Columns;

			PropertyDescriptorCollection col = TypeDescriptor.GetProperties(output);
            IList<string> list = new List<string>(col.Count);


            foreach (PropertyDescriptor item in col)
            {
				if (columns.Contains(item.Name))
				{
                    object value = ObjectExtension.GetValueByType(item.PropertyType, dr[item.Name]);
                    if (value != null)
                    {
						item.SetValue(output, value);
                    }
                }
            }
		}

		/// <summary>
		/// 加载数据
		/// </summary>
		/// <param name="dr">一行数据</param>
		public static void Load<T>(T output, IDataRecord record)
		{
			int count = record.FieldCount;
			IDictionary<string, int> recordlist = new Dictionary<string,int>(count);
			for (int i = 0; i < count; i++)
			{
				recordlist.Add(record.GetName(i),i);
			}

			int r = 0;
			PropertyDescriptorCollection col = TypeDescriptor.GetProperties(output);
			foreach (PropertyDescriptor item in col)
			{
				if (recordlist.ContainsKey(item.Name))
				{
					r = recordlist[item.Name];
					object value = ObjectExtension.GetValueByType(item.PropertyType, record.GetValue(r));
					if (value != null)
					{
						item.SetValue(output, value);
					}
					
				}
			}
		}

		#endregion

	}
}
